<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="Generator" content="EditPlus®">
    <meta name="Author" content="">
    <meta name="Keywords" content="">
    <meta name="Description" content="">
    <title>音乐播放器</title>
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <style>
        body {
            display: block;
            background: url("img/2.jpg");
            background-position: center;
            background-repeat: no-repeat;
            background-attachment: fixed;
            background-size:100%;
        }
        .container{
            position: fixed;
            top: 15px;
            margin-right:-500px;
            width: 1000px;
            height: 800px;
        }
        .music-select{
            width: 450px;
            height: 800px;
            overflow: auto;
        }
        #filebox {
            position: absolute;
            width: 330px;
            height: 30px;
            line-height: 30px;
            text-align: center;
            border: 2px solid rgba(30,144,255,0.5);
            border-radius: 5px;
            background: rgba(30,144,255,0.5);
            display: inline-block;
        }
        #file{
            position: absolute;
            left: 0px;
            opacity: 0;
            height:30px;
            width: 330px;
        }
        #select{
            position: absolute;
            /*margin-left: 12px;*/
            left: 346px;
            height:34px;
            width: 104px;
            border: 2px solid rgba(30,144,255,0.5);
            border-radius: 5px;
            background: rgba(30,144,255,0.5);
            font-size: 14px;
            padding: 5px;
        }
        .music-select .list{
            list-style: none;
            margin: 0px;
            padding: 2px 2px;
            border: 1px solid rgba(30,144,255,0.3);
            margin-top: 38px;
        }
        .music-select .list>li{
            position: relative;
            padding: 5px 5px;
            border: 1px solid rgba(255,215,0, 0.6);
            background-color: rgba(135,206,250, 0.3);
            overflow: hidden;
            cursor: pointer;
            margin: 10px 2px;
        }
        .music-select .list>li:hover{
            background-color:rgba(30,144,255, 0.4);
        }
        .music-select .list>li:active {
            border: 1px solid rgba(255,215,0, 0.6);
        }
        .music-select .list div{
            padding: 1px 2px 1px 2px;
            float: right;
            border: 1px solid rgba(255,215,0, 0.6);
        }
        .music-select .list div:hover{
            border: 1px solid rgba(255,215,0, 0.6);
        }
        .music-select .list>li:active {
            border: 1px solid rgba(255,215,0, 0.6);
        }
        .music-box {
            position: absolute;
            top: 10px;
            left: 63%;
            float: left;
        }
        #button-box{
            position: absolute;
            left: 7%;
        }
        .music-box .buttons{
            display: inline-block;
            width: 150px;
            height: 30px;
            line-height: 30px;
            text-align: center;
            border: 2px solid rgba(30,144,255,0.5);
            border-radius: 5px;
            background: rgba(30,144,255,0.5);
            margin: 5px 20px;
            cursor: pointer;
            top: 100px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="music-select">
            <div id="filebox">
                <input type="file" id="file" class="file" onchange="loadFiles(this)" multiple="multiple" accept="audio/*">
                <span>导入</span>
            </div>
            <select id="select">
                <option>列表循环</option>
                <option>单曲循环</option>
                <option>随机播放</option>
            </select>
            <ul id="list" class="list"></ul>
        </div>
        <div class="music-box">
            <canvas id="wrap"></canvas>
            <div class="button-box" id="button-box" >
                <div class="buttons" id="pre" onclick="preMusic()">上一首</div>
                <div class="buttons" id="startStop">暂停</div>
                <div class="buttons" id="next" onclick="nextMusic()">下一首</div>
            </div>
        </div>
    </div>
    <script>
        var liIdPrefix = 'mli';
        var listContainer = document.getElementById('list');
        var selected = document.getElementById("select")
        var current; // 音乐播放索引
        var fileList = [];
        wrap.width = window.innerWidth-220;
        wrap.height = window.innerHeight-220;
        var AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext;
        var audioContext = new AudioContext();//实例化
        var canvasCtx = wrap.getContext("2d");

        /**
         * 加载音乐文件列表
         */
        function loadFiles(input) {
            if (input.files.length>0){
                fileList = input.files;
                setPlaylist(fileList);
                current = 0;
                loadMusicAndPlay(current);
            }
        }

        /**
         * 展示列表
         */
        function setPlaylist(list){
            var container = document.createDocumentFragment();
            for(var i = 0; i < list.length ; i++ ){
                var file = list[i]
                var node = document.createElement('li');
                node.id = liIdPrefix + i;
                node.innerText = '[' + (i+1) + '] ' + file.name;
                container.appendChild(node);
            }
            // 每次列表添加数据之前，先清空之前的列表
            while (listContainer.firstChild) {
                listContainer.removeChild(listContainer.firstChild);
            }
            listContainer.appendChild(container)
        }

        /**
         * 根据播放方式，播放音乐
         */
        function selectChange(){
            var index = selected.selectedIndex;
            var value = selected.options[index].text;
            console.log(value);
            if (value == '列表循环'){
                if(current >= fileList.length - 1){
                    current = 0;
                    loadMusicAndPlay(current);
                }else{
                    loadMusicAndPlay(++current);
                }
            }else if(value == '单曲循环'){
                // 单曲循环不改变播放索引
                loadMusicAndPlay(current);
            }else {
                // 随机播放，生成随机数
                current = Math.floor(Math.random()*fileList.length);
                loadMusicAndPlay(current);
            }
        }

        /**
         * 双击切换播放
         */
        listContainer.ondblclick = function(e){
            if(e.target.tagName.toLowerCase() === 'li'){
                for(var i = 0; i < this.children.length; i++){
                    if(this.children[i] === e.target){
                        current = i
                    }
                }
                console.log('第%d首', current + 1)
                loadMusicAndPlay(current);
            }
        }

        /**
         * 上一曲
         */
        function preMusic(){
            console.log('点击播放上一首！');
            if (current == 0){
                current = fileList.length-1;
                loadMusicAndPlay(current);
            }else {
                loadMusicAndPlay(--current);
            }
        }

        /**
         * 下一曲
         */
        function nextMusic(){
            console.log('点击播放下一首！');
            if(current >= fileList.length - 1){
                current = 0;
                loadMusicAndPlay(current);
            }else{
                loadMusicAndPlay(++current);
            }
        }

        /**
         * 加载音乐、播放并绘制频谱
         */
        function loadMusicAndPlay(id){
            var file = fileList[id];
            //当选择歌曲时，判断当前audioContext的状态，如果在进行中则关闭音频环境，
            //释放audioContext的所有资源，并重新实例化audioContext
            if(audioContext.state == 'running'){
                audioContext.close();
                audioContext = new AudioContext();
            }
            // 如果音频是暂停状态，又点击了上一首、下一首，则先关闭
            if(audioContext.state === 'suspended' && $("#startStop").text()=='播放') {
                $("#startStop").text('暂停');
                audioContext.close();
                audioContext = new AudioContext();
            }
            var fileReader = new FileReader();
            fileReader.readAsArrayBuffer(file);
            fileReader.onload = function(e) {
                var count = 0;
                var timer = setInterval(function(){
                    count++;
                },1000)
                audioContext.decodeAudioData(e.target.result, function(buffer) {
                    clearInterval(timer)
                    var audioBufferSourceNode = audioContext.createBufferSource();
                    var analyser = audioContext.createAnalyser();
                    audioBufferSourceNode.connect(analyser);
                    analyser.connect(audioContext.destination);
                    audioBufferSourceNode.buffer = buffer;
                    // 监听onended事件，判断音频是否播放完毕，播放完毕继续播放下一首
                    audioBufferSourceNode.onended = () => {
                        console.log('音频播放完毕，开始播放下一首！');
                        selectChange();
                    };
                    audioBufferSourceNode.start();
                    //播放暂停音频
                    startStop.onclick = function() {
                        if(audioContext.state === 'running') {
                            audioContext.suspend().then(function() {
                                $("#startStop").text('播放');
                            });
                        } else if(audioContext.state === 'suspended') {
                            audioContext.resume().then(function() {
                                $("#startStop").text('暂停');
                            });
                        }
                    }
                    // 绘制音频频谱
                    绘制频谱(analyser,file);
                    // draw(analyser);
                })
            }
        }

        function 绘制频谱(analyser,file){
            var oW = wrap.width-900;
            var oH = wrap.height;

            var color1 = canvasCtx.createLinearGradient(oW / 2, oH / 2-10, oW / 2, oH / 2 - 150);
            color1.addColorStop(0, '#1E90FF');
            color1.addColorStop(.25, '#FF7F50');
            color1.addColorStop(.5, '#8A2BE2');
            color1.addColorStop(.75, '#4169E1');
            color1.addColorStop(1, '#00FFFF');

            var color2=canvasCtx.createLinearGradient(0,0,oW,oH);
            color2.addColorStop(0, '#1E90FF');
            color2.addColorStop(.25, '#FFD700');
            color2.addColorStop(.5, '#8A2BE2');
            color2.addColorStop(.75, '#4169E1');
            color2.addColorStop(1, '#FF0000');

            var output = new Uint8Array(180);
            var du = 2;//角度
            var R = 200;//半径
            var W = 5;//宽
            (function drawSpectrum() {
                analyser.getByteFrequencyData(output);
                canvasCtx.clearRect(0, 0, wrap.width, wrap.height);
                for (var i = 0; i < 360; i++) {
                    var value = output[i] / 10;
                    canvasCtx.beginPath();
                    canvasCtx.lineWidth = W;
                    Rv1 = (R -value);
                    Rv2 = (R +value);
                    canvasCtx.moveTo(( Math.sin((i * du) / 180 * Math.PI) * Rv1 + oW/2),-Math.cos((i * du) / 180 * Math.PI) * Rv1 + oH/2);
                    canvasCtx.lineTo( ( Math.sin((i * du) / 180 * Math.PI) * Rv2 + oW/2),-Math.cos((i * du) / 180 * Math.PI) * Rv2 + oH/2);
                    canvasCtx.strokeStyle = color1;//线条的颜色
                    canvasCtx.stroke();
                }
                canvasCtx.font = "20px 华文楷体";
                // 设置颜色
                canvasCtx.fillStyle = color2;
                // 设置水平对齐方式
                canvasCtx.textAlign = "center";
                // 设置垂直对齐方式
                canvasCtx.textBaseline = "middle";
                // 绘制文字（参数：要写的字，x坐标，y坐标）
                canvasCtx.fillText(file.name, oW/2, oH/2);
                requestAnimationFrame(drawSpectrum);
            })();
        }
    </script>
</body>
</html>
